package com.gsafety.library.Exts;

import android.animation.Animator;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Paint;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.PowerManager;
import android.provider.MediaStore;
import android.provider.Settings;
import android.text.Editable;
import android.text.TextPaint;
import android.text.TextWatcher;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.inputmethod.InputMethodManager;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.ColorRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.FloatRange;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.StringRes;
import androidx.annotation.WorkerThread;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner;

import com.gsafety.library.Base.IBaseDialog;
import com.gsafety.library.Medias.Image;
import com.gsafety.library.Medias.OnMediaTakeListener;
import com.gsafety.library.Medias.Video;
import com.gsafety.library.R;
import com.gsafety.library.Utils.DensityUtil;
import com.gsafety.library.ViewModels.AnimLifeViewModel;
import com.gsafety.library.common.ActivityResultFragment;
import com.gsafety.library.common.OnBlockCheckedChangeListener;
import com.gsafety.library.common.OnTextAfterChangedListener;
import com.gsafety.library.common.OnTextBeforeChangedListener;
import com.gsafety.library.common.OnTextChangedListener;
import com.gsafety.library.common.OnUnshakClickListener;
import com.gsafety.library.common.Position;
import com.gsafety.library.common.SPEditor;
import com.gsafety.library.common.SystemAlertCallBack;
import com.gsafety.library.common.SystemAlertDialogI;

import java.io.File;
import java.lang.reflect.Field;
import java.util.Locale;
import java.util.Set;

/**
 * 对于一些常用的功能的扩展
 */
public class Ext
{
    public static void hide(View view)
    {
        view.setVisibility(View.INVISIBLE);
    }

    public static boolean isVisible(View view)
    {
        return view.getVisibility() == View.VISIBLE;
    }

    public static void show(View view)
    {
        view.setVisibility(View.VISIBLE);
    }

    public static void gone(View view)
    {
        view.setVisibility(View.GONE);
    }

    /**
     * 切换VISIBLE显示Viw
     */
    public static void toggleHide(View view)
    {
        if (view.getVisibility() == View.VISIBLE)
        {
            view.setVisibility(View.INVISIBLE);
        } else
        {
            view.setVisibility(View.VISIBLE);
        }
    }


    /**
     * 切换GONE显示Viw
     */
    public static void toggleGone(View view)
    {
        if (view.getVisibility() == View.VISIBLE)
        {
            view.setVisibility(View.GONE);
        } else
        {
            view.setVisibility(View.VISIBLE);
        }
    }

    /**
     * 获取屏幕宽度
     */
    public static int getScreenWidth(Context context)
    {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        return wm.getDefaultDisplay().getWidth();
    }

    /**
     * 获取屏幕高度
     */
    public static int getScreenHeight(Context context)
    {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        return wm.getDefaultDisplay().getHeight();
    }

    /**
     * 单位换算 px 转 sp
     *
     * @param context 上下文
     * @param px      px像素单位
     * @return sp的单位
     */
    public static int px2sp(Context context, int px)
    {
        return DensityUtil.px2sp(context, px);
    }

    /**
     * 单位换算 sp 转 px
     *
     * @param context 上下文
     * @param sp      sp单位
     * @return px像素单位
     */
    public static int sp2px(Context context, int sp)
    {
        return DensityUtil.sp2px(context, sp);
    }

    /**
     * 单位换算 px 转 dp
     *
     * @param context 上下文
     * @param px      px像素
     * @return dp单位
     */
    public static int px2dp(Context context, int px)
    {
        return DensityUtil.px2dip(context, px);
    }

    /**
     * 单位换算 dp 转 px
     *
     * @param context 上下文
     * @param dp      dp单位
     * @return px像素单位
     */
    public static int dp2px(Context context, int dp)
    {
        return DensityUtil.dip2px(context, dp);
    }

    /**
     * 获取颜色
     *
     * @param context 上下文
     * @param res     颜色的资源id
     * @return 颜色的int值
     */
    public static int getColor(Context context, @ColorRes int res)
    {
        return ContextCompat.getColor(context, res);
    }

    /**
     * 获取Drawable
     *
     * @param res
     * @return
     */
    public static Drawable getDrawable(Context context, @DrawableRes int res)
    {
        Drawable drawable = ContextCompat.getDrawable(context, res);
        if (drawable == null)
        {
            drawable = new ColorDrawable();
        }
        return drawable;
    }

    /**
     * 获取字符串
     *
     * @param context 上下文
     * @param res     字符串的资源id
     * @return 字符串的值
     */
    public static String getString(Context context, @StringRes int res)
    {
        return context.getResources().getString(res);
    }

    /**
     * 快捷弹出吐司
     *
     * @param context
     * @param resId
     */
    public static void Toast(Context context, @StringRes int resId)
    {
        if (context != null)
        {
            Toast toast = Toast.makeText(context, "", android.widget.Toast.LENGTH_SHORT);
            toast.setText(resId);
            toast.show();
        }
    }

    /**
     * 快捷弹出吐司
     *
     * @param context
     * @param obj
     */
    public static void Toast(Context context, Object obj)
    {
        if (context != null)
        {
            Toast toast = Toast.makeText(context, "", android.widget.Toast.LENGTH_SHORT);
            toast.setText(String.valueOf(obj));
            toast.show();
        }
    }


    /**
     * 设置界面为黑色标题栏文字的模式
     */
    public static void darkStatusModel(Activity activity)
    {
        View decor = activity.getWindow().getDecorView();
        decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
    }

    /**
     * 设置界面为白色标题栏文字的模式
     */
    public static void lightStatusModel(Activity activity)
    {
        View decor = activity.getWindow().getDecorView();
        decor.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
    }

    /**
     * 获取状态栏的高度
     */
    public static int getStatbarHeight(Context context)
    {
        int result = 0;
        int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0)
        {
            result = context.getResources().getDimensionPixelSize(resourceId);
        }
        if (result == 0)
        {
            try
            {
                Class<?> c = Class.forName("com.android.internal.R$dimen");
                Object obj = c.newInstance();
                Field field = c.getField("status_bar_height");
                int x = Integer.parseInt(field.get(obj).toString());
                result = context.getResources().getDimensionPixelSize(x);
            } catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 测量自定义View的高度
     */
    public static int measureHeight(int heightMeasureSpec)
    {
        int heightResult = 0;
        int heightSpecMode = View.MeasureSpec.getMode(heightMeasureSpec);
        int heightSpecSize = View.MeasureSpec.getSize(heightMeasureSpec);
        switch (heightSpecMode)
        {
            case View.MeasureSpec.UNSPECIFIED:
            {
                heightResult = heightSpecSize;
            }
            break;
            case View.MeasureSpec.AT_MOST:
            {
                heightResult = View.MeasureSpec.getSize(heightMeasureSpec);
            }
            break;
            case View.MeasureSpec.EXACTLY:
            {
                heightResult = View.MeasureSpec.getSize(heightMeasureSpec);
            }
        }
        return heightResult;
    }


    /**
     * 测量自定义View的宽度
     */
    public static int measureWidth(int widthMeasureSpec)
    {
        int widthResult = 0;
        int widthSpecMode = View.MeasureSpec.getMode(widthMeasureSpec);
        int widthSpecSize = View.MeasureSpec.getSize(widthMeasureSpec);
        switch (widthSpecMode)
        {
            case View.MeasureSpec.UNSPECIFIED:
            {
                widthResult = widthSpecSize;
            }
            break;
            case View.MeasureSpec.AT_MOST:
            case View.MeasureSpec.EXACTLY:
            {
                widthResult = View.MeasureSpec.getSize(widthMeasureSpec);
            }
            break;
        }
        return widthResult;
    }

    /**
     * 自动根据系统的版本，获取对应的Uri
     */
    public static Uri toUri(Context context, File file)
    {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
        {
            return FileProvider.getUriForFile(context, String.format(Locale.CHINA, "%s.file_provider", context.getPackageName()), file);
        } else
        {
            return Uri.fromFile(file);
        }
    }

    /**
     * 获取界面的透明度
     *
     * @param activity 界面
     * @return 透明度
     */
    public static float getAlpha(Activity activity)
    {
        Window window = activity.getWindow();
        WindowManager.LayoutParams attr = window.getAttributes();
        return attr.alpha;
    }

    /**
     * 设置界面透明度
     *
     * @param activity 界面
     * @param alpha    透明度
     */
    public static void setAlpha(Activity activity, @FloatRange(from = 0.0, to = 1.0) float alpha)
    {
        Window window = activity.getWindow();
        WindowManager.LayoutParams attr = window.getAttributes();
        attr.alpha = alpha;
        window.setAttributes(attr);
    }

    public static float spGet(Context context, String fileName, String key, float defValue)
    {
        SharedPreferences sp = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
        return sp.getFloat(key, defValue);
    }

    public static int spGet(Context context, String fileName, String key, int defValue)
    {
        SharedPreferences sp = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
        return sp.getInt(key, defValue);
    }

    public static long spGet(Context context, String fileName, String key, long defValue)
    {
        SharedPreferences sp = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
        return sp.getLong(key, defValue);
    }

    public static Set<String> spGet(Context context, String fileName, String key, Set<String> defValue)
    {
        SharedPreferences sp = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
        return sp.getStringSet(key, defValue);
    }

    public static String spGet(Context context, String fileName, String key, String defValue)
    {
        SharedPreferences sp = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
        return sp.getString(key, defValue);
    }

    /**
     * 对SharedPreferences 进行存值取值
     */
    public static void spEdit(Context context, String fileName, SPEditor block)
    {
        SharedPreferences sp = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        block.edit(editor);
        editor.apply();
        editor.commit();
    }

    /**
     * 弹出软键盘
     *
     * @param context 上下文
     * @param view    聚焦的控件
     */
    public static void showKeyboard(Context context, View view)
    {
        InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
        view.requestFocus();
        if (imm != null)
        {
            imm.showSoftInput(view, 0);
        }
    }

    /**
     * 收起软键盘
     *
     * @param activity
     */
    public static void hideSoftKeyboard(Activity activity)
    {
        InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm != null)
        {
            imm.hideSoftInputFromWindow(activity.getWindow().getDecorView().getWindowToken(), 0);
        }
    }

    /**
     * 快捷对ViewModel进行实例化
     *
     * @param klass viewmodel的类
     * @param <T>
     * @return 实例
     */
    public static <T extends ViewModel> T create(ViewModelStoreOwner owner, Class<T> klass)
    {
        return new ViewModelProvider(owner).get(klass);
    }

    /**
     * 启动页面
     *
     * @param context 上下文
     * @param klass   需要启动得类
     * @param bundle  携带得参数，有可能为null
     */
    public static void start(Context context, Class<? extends Activity> klass, @Nullable Bundle bundle)
    {
        Intent intent = new Intent(context, klass);
        if (bundle != null)
        {
            intent.putExtras(bundle);
        }
        if (!(context instanceof Activity))
        {
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        }
        context.startActivity(intent);
    }


    /**
     * 启动界面，并以回调的形式返回数据
     *
     * @param activity         在哪个界面启用的
     * @param klass            启用哪个页面
     * @param bundle           是否需要传递数据
     * @param onActivityResult 回调函数
     */
    public static void startForResult(FragmentActivity activity, Class<? extends Activity> klass, @Nullable Bundle bundle, @Nullable ActivityResultFragment.OnActivityResult onActivityResult)
    {
        FragmentManager fragmentManager = activity.getSupportFragmentManager();
        ActivityResultFragment resultFragment = (ActivityResultFragment) fragmentManager.findFragmentByTag(FragmentManager.class.getName());
        if (resultFragment == null)
        {
            resultFragment = new ActivityResultFragment();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.add(resultFragment, FragmentManager.class.getName());
            transaction.commitAllowingStateLoss();
            fragmentManager.executePendingTransactions();
        }
        ActivityResultFragment.ResultViewModel viewModel = create(resultFragment, ActivityResultFragment.ResultViewModel.class);

        Intent intent = new Intent(activity, klass);
        ActivityResultFragment.ActivityResultWrapper wrapper = new ActivityResultFragment.ActivityResultWrapper(intent);
        if (bundle != null)
        {
            wrapper.setBundle(bundle);
        }
        if (onActivityResult != null)
        {
            wrapper.setOnActivityResult(onActivityResult);
        }
        viewModel.liveData.setValue(wrapper);
    }

    /**
     * 启动界面，并以回调的形式返回数据
     *
     * @param fragment         在哪个界面启用的
     * @param klass            启用哪个页面
     * @param bundle           是否需要传递数据
     * @param onActivityResult 回调函数
     */
    public static void startForResult(Fragment fragment, Class<? extends Activity> klass, @Nullable Bundle bundle, @Nullable ActivityResultFragment.OnActivityResult onActivityResult)
    {
        if (fragment.isAdded())
        {
            FragmentActivity activity = fragment.requireActivity();
            FragmentManager fragmentManager = activity.getSupportFragmentManager();

            ActivityResultFragment resultFragment = (ActivityResultFragment) fragmentManager.findFragmentByTag(FragmentManager.class.getName());
            if (resultFragment == null)
            {
                resultFragment = new ActivityResultFragment();
                FragmentTransaction transaction = fragmentManager.beginTransaction();
                transaction.add(resultFragment, FragmentManager.class.getName());
                // 提交数据，这里一执行，fragment的onCreate不会立刻执行，
                transaction.commitAllowingStateLoss();
                // 执行这一行，强制执行fragment的添加到activity
                fragmentManager.executePendingTransactions();
            }
            ActivityResultFragment.ResultViewModel viewModel = create(resultFragment, ActivityResultFragment.ResultViewModel.class);
            Intent intent = new Intent(activity, klass);
            ActivityResultFragment.ActivityResultWrapper wrapper = new ActivityResultFragment.ActivityResultWrapper(intent);
            if (bundle != null)
            {
                wrapper.setBundle(bundle);
            }
            if (onActivityResult != null)
            {
                wrapper.setOnActivityResult(onActivityResult);
            }
            viewModel.liveData.setValue(wrapper);
        } else
        {
            throw new RuntimeException(fragment + " 需要在被添加之后才可以使用\n fragment.isAdded()=false");
        }
    }

    /**
     * 启动页面
     *
     * @param fragment 上下文
     * @param klass    需要启动得类
     * @param bundle   携带得参数，有可能为null
     */
    public static void start(Fragment fragment, Class<? extends Activity> klass, @Nullable Bundle bundle)
    {
        Intent intent = new Intent(fragment.requireContext(), klass);
        if (bundle != null)
        {
            intent.putExtras(bundle);
        }
        fragment.startActivity(intent);
    }


    /**
     * 获取图片存储位置
     */
    public static File getImgDir(Context context)
    {
        return context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    }

    /**
     * 获取临时文件存储位置
     */
    public static File getTmpDir(Context context)
    {
        return context.getExternalFilesDir(null);
    }

    /**
     * 弹窗
     *
     * @param title 标题
     */
    public static IBaseDialog Alert(Context context, String title)
    {
        SystemAlertDialogI dialog = new SystemAlertDialogI(context, title, null, null, null, false);
        dialog.show();
        return dialog;
    }

    /**
     * 弹窗
     *
     * @param title        标题
     * @param completeText 确认按钮
     */
    public static IBaseDialog Alert(Context context, String title, String completeText)
    {
        SystemAlertDialogI dialog = new SystemAlertDialogI(context, title, null, completeText, null, false);
        dialog.show();
        return dialog;
    }

    /**
     * 弹窗
     *
     * @param title         标题
     * @param completeText  确认按钮
     * @param completeBlock 确认按钮点击事件
     */
    public static IBaseDialog Alert(Context context, String title, String completeText, SystemAlertCallBack completeBlock)
    {
        SystemAlertDialogI dialog = new SystemAlertDialogI(context, title, null, completeText, null, false);
        dialog.setCompleteBlock(completeBlock);
        dialog.show();
        return dialog;
    }


    /**
     * 弹窗
     *
     * @param title        标题
     * @param completeText 确认按钮
     * @param navigateText 第二个按钮
     */
    public static IBaseDialog Alert(Context context, String title, String completeText, String navigateText)
    {
        SystemAlertDialogI dialog = new SystemAlertDialogI(context, title, null, completeText, navigateText, false);
        dialog.show();
        return dialog;
    }


    /**
     * 弹窗
     *
     * @param title         标题
     * @param completeText  确认按钮
     * @param navigateText  第二个按钮
     * @param completeBlock 确认按钮事件
     * @param navigateBlock 第二个按钮事件
     */
    public static IBaseDialog Alert(Context context, String title, String completeText, SystemAlertCallBack completeBlock, String navigateText, SystemAlertCallBack navigateBlock)
    {
        SystemAlertDialogI dialog = new SystemAlertDialogI(context, title, null, completeText, navigateText, false);
        dialog.setCompleteBlock(completeBlock);
        dialog.setNavigateBlock(navigateBlock);
        dialog.show();
        return dialog;
    }

    /**
     * 弹窗
     *
     * @param title         标题
     * @param msg           内容信息
     * @param completeText  确认按钮
     * @param navigateText  第二个按钮
     * @param completeBlock 确认按钮事件
     * @param navigateBlock 第二个按钮事件
     */
    public static IBaseDialog Alert(Context context, String title, String msg, String completeText, SystemAlertCallBack completeBlock, String navigateText, SystemAlertCallBack navigateBlock)
    {
        SystemAlertDialogI dialog = new SystemAlertDialogI(context, title, msg, completeText, navigateText, false);
        dialog.setCompleteBlock(completeBlock);
        dialog.setNavigateBlock(navigateBlock);
        dialog.show();
        return dialog;
    }

    /**
     * 文字改变之前
     */
    public static void beforeTextChanged(EditText editText, final OnTextBeforeChangedListener listener)
    {
        editText.addTextChangedListener(new TextWatcher()
        {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after)
            {
                listener.beforeTextChanged(s, start, count, after);
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2)
            {

            }

            @Override
            public void afterTextChanged(Editable editable)
            {

            }
        });
    }

    /**
     * 文字正在改变
     */
    public static void onTextChanged(EditText editText, final OnTextChangedListener listener)
    {
        editText.addTextChangedListener(new TextWatcher()
        {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after)
            {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count)
            {
                listener.textChanged(s, start, before, count);
            }

            @Override
            public void afterTextChanged(Editable editable)
            {

            }
        });
    }

    /**
     * 文字改变之后
     */
    public static void onAfterChanged(EditText editText, final OnTextAfterChangedListener listener)
    {
        editText.addTextChangedListener(new TextWatcher()
        {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after)
            {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count)
            {
            }

            @Override
            public void afterTextChanged(Editable editable)
            {
                listener.afterTextChanged(editable);
            }
        });
    }

    /**
     * 防止抖动点击事件
     * 500毫秒之内不允许两次点击
     */
    public static void setUnShakeClickListener(View view, OnUnshakClickListener listener)
    {
        view.setOnClickListener(listener);
    }

    /**
     * @param checked  选中状态
     * @param useBlock 是否响应改变回调
     */
    public static void setChecked(CheckBox checkBox, boolean checked, boolean useBlock)
    {
        if (checkBox.isChecked() != checked)
        {
            checkBox.setTag(R.id.checkbox_invoke_flag, useBlock);
        }
        checkBox.setChecked(checked);
    }

    /**
     * 设置有条件的响应选中事件
     *
     * @param checkBox
     * @param listener
     */
    public static void setOnCheckedChange(CheckBox checkBox, final OnBlockCheckedChangeListener listener)
    {
        checkBox.setOnCheckedChangeListener(listener);
    }

    /**
     * 围绕 TextView 指定位置显示图标
     *
     * @param textView
     * @param res
     * @param position
     */
    public static void draw(TextView textView, @DrawableRes int res, Position position)
    {
        Drawable drawable = textView.getResources().getDrawable(res);
        if (drawable != null)
        {
            drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        }

        switch (position)
        {
            case LEFT:
            {
                textView.setCompoundDrawables(drawable, null, null, null);
            }
            break;
            case RIGHT:
            {
                textView.setCompoundDrawables(null, null, drawable, null);
            }
            break;
            case TOP:
            {
                textView.setCompoundDrawables(null, drawable, null, null);
            }
            break;
            case BOTTOM:
            {
                textView.setCompoundDrawables(null, null, null, drawable);
            }
            break;
        }
    }

    /**
     * 下划线
     *
     * @param textView
     */
    public static void underLine(TextView textView)
    {
        TextPaint paint = textView.getPaint();
        paint.setFlags(Paint.UNDERLINE_TEXT_FLAG); //下划线
        paint.setAntiAlias(true);//抗锯齿
    }

    /**
     * 拨打电话
     *
     * @param number
     */
    public static void call(Context context, String number) throws Exception
    {
        Intent intent = new Intent(Intent.ACTION_DIAL);
        Uri data = Uri.parse("tel:" + number);
        intent.setData(data);
        context.startActivity(intent);
    }

    /**
     * 获取唯一识别码，只能依靠 刷机/重置 来重置的ID
     *
     * @param context
     * @return
     */
    public static String getAndroidID(Context context)
    {
        return Settings.System.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
    }

    /**
     * 清空Edittext的内容
     *
     * @param editText
     */
    public static <T extends EditText> void clear(T editText)
    {
        editText.getText().clear();
    }

    /**
     * 判断我们的应用是否在电池优化白名单中
     *
     * @param context
     * @return
     */
    @RequiresApi(api = Build.VERSION_CODES.M)
    public static boolean isIgnoringBatteryOptimizations(Context context)
    {
        boolean isIgnoring = false;
        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        if (powerManager != null)
        {
            isIgnoring = powerManager.isIgnoringBatteryOptimizations(context.getPackageName());
        }
        return isIgnoring;
    }

    /**
     * 申请加入电池优化白名单
     *
     * @param context
     */
    @RequiresApi(api = Build.VERSION_CODES.M)
    public static void requestIgnoreBatteryOptimizations(Context context)
    {
        try
        {
            // 直接申请权限
            Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
            intent.setData(Uri.parse("package:" + context.getPackageName()));
            context.startActivity(intent);
        } catch (Exception e)
        {
            try
            {
                // 跳转到设置
                Intent intent1 = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
                context.startActivity(intent1);
            } catch (Exception e1)
            {
                e1.printStackTrace();
            }
        }
    }

    /**
     * 安装APK
     *
     * @param context
     * @param file
     */
    public static void installApk(Context context, String authority, File file)
    {
        Intent install = new Intent(Intent.ACTION_VIEW);
        install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        Uri uri = FileProvider.getUriForFile(context, authority, file);
        install.setDataAndType(uri, "application/vnd.android.package-archive");
        context.startActivity(install);
    }

    /**
     * 安装APK
     *
     * @param context
     * @param file
     */
    public static void installApk(Context context, File file)
    {
        installApk(context, context.getPackageName() + ".file_provider", file);
    }


    /**
     * 启动动画，当生命周期结束，会自动结束动画
     *
     * @param storeOwner     activity/fragment/ 所有支持ViewModelStoreOwner的对象
     * @param lifecycleOwner activity/fragment/ 所有支持ViewModelStoreOwner的对象
     * @param animator       需要启动的动画
     */
    public static void startWith(ViewModelStoreOwner storeOwner, LifecycleOwner lifecycleOwner, Animator animator)
    {
        AnimLifeViewModel viewModel = create(storeOwner, AnimLifeViewModel.class);
        lifecycleOwner.getLifecycle().addObserver(viewModel);
        viewModel.start(animator);
    }

    /**
     * 启动动画，当生命周期结束，会自动结束动画
     *
     * @param storeOwner     activity/fragment/ 所有支持ViewModelStoreOwner的对象
     * @param lifecycleOwner activity/fragment/ 所有支持ViewModelStoreOwner的对象
     * @param animation      需要启动的动画
     */
    public static void startWith(ViewModelStoreOwner storeOwner, LifecycleOwner lifecycleOwner, Animation animation)
    {
        AnimLifeViewModel viewModel = create(storeOwner, AnimLifeViewModel.class);
        lifecycleOwner.getLifecycle().addObserver(viewModel);
        viewModel.start(animation);
    }

    /**
     * 查询媒体资源-视频
     */
    // Manifest.permission.READ_EXTERNAL_STORAGE
    @WorkerThread
    public static void queryMediaVideo(Context context, OnMediaTakeListener<Video> listener)
    {
        String[] projection = new String[]{
                MediaStore.Video.Media._ID,
                MediaStore.Video.Media.DISPLAY_NAME,
                MediaStore.Video.Media.SIZE,
                MediaStore.Video.Media.MIME_TYPE,
                MediaStore.Video.Media.DATE_MODIFIED,
                MediaStore.Video.Media.DATE_ADDED,
        };

        String order = MediaStore.Video.Media.DATE_MODIFIED + " DESC";
        ContentResolver resolver = context.getContentResolver();
        try (Cursor cursor = resolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, projection, "", null, order))
        {
            assert cursor != null;
            while (cursor.moveToNext())
            {
                long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Video.Media._ID));
                String display_name = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DISPLAY_NAME));
                long size = cursor.getLong(cursor.getColumnIndex(MediaStore.Video.Media.SIZE));
                String mimeType = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.MIME_TYPE));
                long date_modified = cursor.getLong(cursor.getColumnIndex(MediaStore.Video.Media.DATE_MODIFIED));
                long date_added = cursor.getLong(cursor.getColumnIndex(MediaStore.Video.Media.DATE_ADDED));
                // 把ID转换成URi
                Uri contentUri = ContentUris.withAppendedId(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, id);

                Video video = new Video();
                video.setId(id);
                video.setContentUri(contentUri);
                video.setMimeType(mimeType);
                video.setDisplay_name(display_name);
                video.setSize(size);
                video.setDate_added(date_added);
                video.setDate_modified(date_modified);
                if (listener != null)
                {
                    listener.onTake(video);
                }
            }
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    /**
     * 查询媒体资源-图片
     */
    // Manifest.permission.READ_EXTERNAL_STORAGE
    @WorkerThread
    public static void queryMediaImage(Context context, OnMediaTakeListener<Image> listener)
    {
        String[] projection = new String[]{
                MediaStore.Images.Media._ID,
                MediaStore.Images.Media.DISPLAY_NAME,
                MediaStore.Images.Media.SIZE,
                MediaStore.Images.Media.MIME_TYPE,
                MediaStore.Images.Media.DATE_MODIFIED,
                MediaStore.Images.Media.DATE_ADDED,
        };

        String order = MediaStore.Images.Media.DATE_MODIFIED + " DESC";
        ContentResolver resolver = context.getContentResolver();
        try (Cursor cursor = resolver.query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, "", null, order))
        {
            assert cursor != null;
            while (cursor.moveToNext())
            {
                long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media._ID));
                String display_name = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME));
                long size = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.SIZE));
                String mimeType = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE));
                long date_modified = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_MODIFIED));
                long date_added = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.Media.DATE_ADDED));
                // 把ID转换成URi
                Uri contentUri = ContentUris.withAppendedId(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id);
                
                Image image = new Image();
                image.setId(id);
                image.setContentUri(contentUri);
                image.setMimeType(mimeType);
                image.setDisplay_name(display_name);
                image.setSize(size);
                image.setDate_added(date_added);
                image.setDate_modified(date_modified);

                if (listener != null)
                {
                    listener.onTake(image);
                }
            }
        } catch (Exception e)
        {
            e.printStackTrace();
        }
    }

}
